package com.ias.system.user.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ias.redis.support.CacheNames;
import com.ias.system.user.entity.User;
import com.ias.system.user.mapper.UserMapper;
import com.ias.system.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * 用户服务实现类
 * 演示动态数据源的使用
 * 
 * @author IAS Team
 * @since 1.0.0
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    /**
     * 分页查询用户 - 使用从库（读库）
     * 基于MyBatis-Plus 3.5.9优化，使用LambdaQueryWrapper提供类型安全
     * @DS注解指定使用slave数据源
     */
    @Override
//    @DS("slave")
//    @Cacheable( cacheNames = CacheNames.CACHE_60MINS,cacheManager = "L2_CacheManager", key = "'keyword'+#keyword", sync = true)
    public IPage<User> selectUserPage(Page<User> page, String keyword) {
        log.info("使用从库查询用户列表，关键词：{}", keyword);
        
        // 使用LambdaQueryWrapper替代QueryWrapper，提供类型安全和更好的IDE支持
        LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
        
        if (StringUtils.hasText(keyword)) {
            // 使用lambda表达式，避免字段名硬编码
            queryWrapper.and(wrapper -> 
                wrapper.like(User::getUsername, keyword)
                    .or().like(User::getRealName, keyword)
                    .or().like(User::getPhone, keyword)
                    .or().like(User::getEmail, keyword)
            );
        }
        
        // 按创建时间倒序 - 使用lambda表达式
        queryWrapper.orderByDesc(User::getCreateTime);
        
        return baseMapper.selectPage(page, queryWrapper);
    }

    /**
     * 重置密码 - 使用主库（写库）
     * @DS注解指定使用master数据源
     */
    @Override
    @DS("master")
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(Long userId) {
        log.info("使用主库重置用户密码，用户ID：{}", userId);
        
        User user = baseMapper.selectById(userId);
        if (user == null) {
            log.warn("用户不存在，ID：{}", userId);
            return false;
        }
        
        // 重置为默认密码：123456
        String defaultPassword = passwordEncoder.encode("123456");
        user.setPassword(defaultPassword);
        
        int result = baseMapper.updateById(user);
        log.info("重置密码结果：{}", result > 0 ? "成功" : "失败");
        
        return result > 0;
    }

    /**
     * 修改密码 - 使用主库（写库）
     */
    @Override
    @DS("master")
    @Transactional(rollbackFor = Exception.class)
    public boolean changePassword(String oldPassword, String newPassword) {
        log.info("使用主库修改用户密码");
        
        // 这里简化处理，实际应该从SecurityContext获取当前用户
        // 为了演示，我们使用admin用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", "admin");
        User user = baseMapper.selectOne(queryWrapper);
        
        if (user == null) {
            log.warn("用户不存在");
            return false;
        }
        
        // 验证旧密码
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            log.warn("旧密码不正确");
            return false;
        }
        
        // 设置新密码
        user.setPassword(passwordEncoder.encode(newPassword));
        int result = baseMapper.updateById(user);
        
        log.info("修改密码结果：{}", result > 0 ? "成功" : "失败");
        return result > 0;
    }

    /**
     * 保存用户 - 使用主库（写库）
     */
    @Override
    @DS("master")
    @Transactional(rollbackFor = Exception.class)
    public boolean save(User entity) {
        log.info("使用主库保存用户：{}", entity.getUsername());
        
        // 加密密码
        if (StringUtils.hasText(entity.getPassword())) {
            entity.setPassword(passwordEncoder.encode(entity.getPassword()));
        }
        
        return super.save(entity);
    }

    /**
     * 更新用户 - 使用主库（写库）
     */
    @Override
    @DS("master")
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(User entity) {
        log.info("使用主库更新用户：{}", entity.getId());
        
        // 如果密码不为空，则加密
        if (StringUtils.hasText(entity.getPassword())) {
            entity.setPassword(passwordEncoder.encode(entity.getPassword()));
        }
        
        return super.updateById(entity);
    }

    /**
     * 删除用户 - 使用主库（写库）
     */
    @DS("master")
    @Transactional(rollbackFor = Exception.class)
    public boolean removeById(Long id) {
        log.info("使用主库删除用户：{}", id);
        return super.removeById(id);
    }

    /**
     * 根据ID查询用户 - 使用从库（读库）
     */
    @DS("slave")
    public User getById(Long id) {
        log.info("使用从库查询用户详情：{}", id);
        return super.getById(id);
    }

    /**
     * 根据用户名查询用户 - 使用从库（读库）
     */
    @DS("slave")
    public User getUserByUsername(String username) {
        log.info("使用从库根据用户名查询用户：{}", username);
        
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 统计用户数量 - 使用从库（读库）
     */
    @DS("slave")
    public long countUsers() {
        log.info("使用从库统计用户数量");
        return baseMapper.selectCount(null);
    }

    /**
     * 批量保存用户 - 使用主库（写库）
     */
    @DS("master")
    @Transactional(rollbackFor = Exception.class)
    public boolean saveBatch(java.util.List<User> entityList) {
        log.info("使用主库批量保存用户，数量：{}", entityList.size());
        
        // 批量加密密码
        entityList.forEach(user -> {
            if (StringUtils.hasText(user.getPassword())) {
                user.setPassword(passwordEncoder.encode(user.getPassword()));
            }
        });
        
        return super.saveBatch(entityList);
    }
}
